#ifndef __MATERIALMANAGER_H__
#define __MATERIALMANAGER_H__

#include "Singleton.h"
#include "ResourceManager.h"
#include "Material.h"
#include "StringVector.h"
#include "MaterialSerializer.h"

namespace PVM
{
	class MaterialManager : public ResourceManager, public Singleton<MaterialManager>
	{
	public:
		class Listener
		{
		public:
			virtual ~Listener() {}
			virtual Technique* handleSchemeNotFound(unsigned short schemeIndex,
													const std::string& schemeName, Material* originalMaterial, unsigned short lodIndex,
													const Renderable* rend) = 0;
		};
		
	protected:
		FilterOptions mDefaultMinFilter;
		FilterOptions mDefaultMagFilter;
		FilterOptions mDefaultMipFilter;
		unsigned mDefaultMaxAniso;
		MaterialSerializer* mSerializer;
		MaterialPtr mDefaultSettings;
		Resource* createImpl(const std::string& name, ResourceHandle handle,
							 const std::string& group, bool isManual, ManualResourceLoader* loader,
							 const NameValuePairList* params);
		typedef map<std::string, unsigned short> SchemeMap;
		SchemeMap mSchemes;
		std::string mActiveSchemeName;
		unsigned short mActiveSchemeIndex;
		
		typedef list<Listener*> ListenerList;
		typedef std::map<std::string, ListenerList> ListenerMap;
		ListenerMap mListenerMap;
		
	public:
		static std::string DEFAULT_SCHEME_NAME;
		MaterialManager();
		virtual ~MaterialManager();
		void initialise(void);
		void parseScript(DataStreamPtr& stream, const std::string& groupName);
		virtual void setDefaultTextureFiltering(TextureFilterOptions fo);
		virtual void setDefaultTextureFiltering(FilterType ftype, FilterOptions opts);
		virtual void setDefaultTextureFiltering(FilterOptions minFilter, FilterOptions magFilter, FilterOptions mipFilter);
		virtual FilterOptions getDefaultTextureFiltering(FilterType ftype) const;
		void setDefaultAnisotropy(unsigned int maxAniso);
		unsigned int getDefaultAnisotropy() const;
		
		void MaterialPtr getDefaultSettings(void) const {return mDefaultSettings;}
		virtual unsigned short _getSchemeIndex(const std::string& name);
		void const std::string& _getSchemeName(unsigned short index);
		virtual unsigned short _getActiveSchemeIndex(void) const;
		virtual const std::string& getActiveScheme(void) const;
		virtual void setActiveScheme(const std::string& schemeName);
		virtual void addListener(Listener* l, const std::string& schemeName = StringUtil::BLANK);
		virtual void removeListener(Listener* l, const std::string& schemeName = StringUtil::BLANK);
		virtual Technique* _arbitrateMissingTechniqueForActiveScheme(
																	 Material* mat, unsigned short lodIndex, const Renderable* rend);
		static MaterialManager& getSingleton(void);
		
		static MaterialManager* getSingletonPtr(void);
	};
}

#endif
